package com.sky.controller.admin;

import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.properties.JwtProperties;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.utils.JwtUtil;
import com.sky.vo.EmployeeLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 员工管理
 */
@RestController
@RequestMapping("/admin/employee")  //然而前端点击登录后F12查看Request URL，却不是这个路径，这是因为Nginx在前后端之间做了反向代理
@Slf4j
@Api(tags = "员工相关接口")  //Swagger常用注解，一般用在Controller类，表示对类的说明
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")   //Swagger常用注解，一般用于Controller类的方法，表示对方法的说明。实际影响：打开下面的接口文档地址后，会出现左侧你写的“员工登录”4个字
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        log.info("员工登录：{}", employeeLoginDTO);

        Employee employee = employeeService.login(employeeLoginDTO);

        //登录成功后，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()  //builder()，即通过构建器的方式来封装一个对象，以前都是用new一个对象来封装的
                .id(employee.getId())
                .userName(employee.getUsername())
                .name(employee.getName())
                .token(token)
                .build();

        return Result.success(employeeLoginVO);
    }

    /**
     * 退出
     *
     * @return
     */
    @PostMapping("/logout")
    @ApiOperation("员工退出")  //同上，value可以省略
    public Result<String> logout() {
        return Result.success();
    }

    /**
     * 下面是“新增员工”代码
     * @param employeeDTO
     * @return
     */
    //设计一个DTO来封装前端输入过来的数据，不用DTO用employee对象来封装也行，建议：当前端提交的
    // 数据和实体类中对应的属性差别比较大时，建议使用DTO来封装数据。这里employee对象的属性比前端“新增员工”页面提交过来的要多很多，所以用employeeDTO来接收
    //因为接口文档说是post请求，所以加注解@PostMapping（顾名思义）。又因为请求路径是/admin/employee，最上面已经注解过了，就不用了
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){        //因为前端传过来的是json格式，所以用@RequestBody注解。
        log.info("新增员工{}",employeeDTO);       //{}是占位符，程序运行时会把后面的参数动态地拼到占位符里
        System.out.println("当前线程的id：" + Thread.currentThread().getId());
        employeeService.save(employeeDTO);      //调用service的方法来真正完成“新增”操作,save()还没定义，Alt+回车，去定义
        return Result.success();  //统一规定，后端返回给前端的数据统一封装成一个result对象
    }

    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")  //接口文档说了是get请求，至于接口文档的路径/admin/employee/page，只需写page，前两个路径本页最上面已经写了
    @ApiOperation(value = "员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){          //接收前端提交过来的数据，看接口文档，前端传过来的Query类型而非json类型，所以不用加RequestBody注解，而且一共有三个对象,EmployeePageQueryDTO专门定义了这三个对象来接收他
        log.info("员工分页查询，参数为：{}",employeePageQueryDTO);    //写这个是为了便于调试程序，看控制台有无输出这个日志，来判断程序运行的怎么样
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);     //分页查询的结果统一封装在PageResult里，返回给前端再封装成Result,即下一句
        return Result.success(pageResult); //后端返回给前端的数据统一封装成一个result对象
    }

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")      //接口文档说的，status是path参数，所以放到路径里
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status,Long id){     //status是path参数，所以加注解@PathVariable。
        log.info("启用禁用员工账号：{},{}",status,id);
        employeeService.startOrStop(status,id);//后绪步骤定义
        return Result.success();
    }

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")         //大概懂什么时候用get请求了，像这种需要传入某些参数才能操作的就用get？
    @ApiOperation("根据id查询员工信息")
    public Result<Employee> getById(@PathVariable Long id){    //因为接口文档里data里面的数据可以说就是一个Employee，所以泛型里用Employee
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     * @return
     */
    @PutMapping
    @ApiOperation("编辑员工信息")
    public Result update(@RequestBody EmployeeDTO employeeDTO){       //因为不是一个查询性的操作，所以result里的泛型就不指定了
        log.info("编辑员工信息：{}", employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }


}
